import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
# 解决中文显示问题 - 使用支持中文的字体
try:
    # Windows 系统使用微软雅黑
    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
    # MacOS 系统使用苹方字体
    # plt.rcParams['font.sans-serif'] = ['PingFang HK']
except:
    # 如果找不到指定字体，尝试使用系统默认支持中文的字体
    plt.rcParams['font.sans-serif'] = ['SimHei', 'Heiti TC', 'STHeiti']

# 解决负号显示问题
plt.rcParams['axes.unicode_minus'] = False
# ==================== 数据准备 ====================
iris = datasets.load_iris()
X = iris.data
y = iris.target

# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=12
)

# ==================== 测试不同K值 ====================
# 尝试多个K值观察效果
k_values = range(1, 31)  # 测试K=1到30
accuracies = []

for k in k_values:
    # 创建KNN分类器
    knn = KNeighborsClassifier(n_neighbors=k)

    # 训练模型
    knn.fit(X_train, y_train)

    # 预测并计算准确率
    y_pred = knn.predict(X_test)
    accuracy = accuracy_score(y_test, y_pred)
    accuracies.append(accuracy)

    # 打印当前K值的结果
    print(f"K={k:<2} | 准确率: {accuracy:.4f}")

# ==================== 可视化结果 ====================
plt.figure(figsize=(10, 6))
plt.plot(k_values, accuracies, 'bo-', linewidth=2, markersize=8)
plt.title('KNN不同K值在鸢尾花数据集上的准确率')
plt.xlabel('K值 (n_neighbors)')
plt.ylabel('预测准确率')
plt.axhline(y=max(accuracies), color='r', linestyle='--', alpha=0.7)
plt.grid(True, linestyle='--', alpha=0.7)
plt.xticks(k_values)
plt.tight_layout()

# 标记最佳K值
best_k = k_values[np.argmax(accuracies)]
best_acc = max(accuracies)
plt.annotate(f'最佳K值: {best_k}\n准确率: {best_acc:.4f}',
             xy=(best_k, best_acc),
             xytext=(best_k + 5, best_acc - 0.05),
             arrowprops=dict(facecolor='black', shrink=0.05))

plt.savefig('knn_k_values_accuracy.png', dpi=300)
plt.show()

# ==================== 详细分析 ====================
print("\n===== 分析结论 =====")
print(f"准确率变化范围: {min(accuracies):.4f} - {max(accuracies):.4f}")
print(f"准确率变化超过0.01的K值数量: {len([a for a in accuracies if abs(a - best_acc) > 0.01])}")
print(f"准确率保持稳定的范围: K={min(k_values)} 到 K={max(k_values)}")